package com.lottery.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.lottery.common.enums.ActivityStatusEnum;
import com.lottery.common.enums.ResultCodeEnum;
import com.lottery.common.exception.BizException;
import com.lottery.entity.*;
import com.lottery.mapper.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Random;

@Service
@RequiredArgsConstructor
public class LotteryService {
    private final LotteryActivityMapper activityMapper;
    private final LotteryPrizeMapper prizeMapper;
    private final LotteryParticipationMapper participationMapper;
    private final LotteryWinnerMapper winnerMapper;
    private final Random random = new Random();

    /**
     * 查询进行中的活动
     */
    public List<LotteryActivity> getOngoingActivities() {
        return activityMapper.selectOngoingActivities();
    }

    /**
     * 参与抽奖
     */
    @Transactional(rollbackFor = Exception.class)
    public LotteryWinner participate(Integer userId, Integer activityId, String ipAddress, String deviceId) {
        // 1. 校验活动
        LotteryActivity activity = checkActivity(activityId);
        
        // 2. 校验参与次数
        checkParticipationLimit(userId, activityId);
        
        // 3. 记录参与
        recordParticipation(userId, activityId, ipAddress, deviceId);
        
        // 4. 抽奖
        LotteryPrize prize = drawPrize(activityId);
        if (prize == null) {
            return null; // 未中奖
        }
        
        // 5. 扣减库存
        if (prizeMapper.decreaseStock(prize.getPrizeId()) <= 0) {
            throw new BizException(ResultCodeEnum.PRIZE_STOCK_EMPTY.getCode(), 
                                  ResultCodeEnum.PRIZE_STOCK_EMPTY.getMessage());
        }
        
        // 6. 记录中奖
        return recordPrizeWinner(userId, activityId, prize.getPrizeId());
    }

    /**
     * 校验活动
     */
    private LotteryActivity checkActivity(Integer activityId) {
        LotteryActivity activity = activityMapper.selectById(activityId);
        if (activity == null) {
            throw new BizException(ResultCodeEnum.ACTIVITY_NOT_EXIST.getCode(), 
                                  ResultCodeEnum.ACTIVITY_NOT_EXIST.getMessage());
        }
        
        LocalDateTime now = LocalDateTime.now();
        if (activity.getActivityStatus().equals(ActivityStatusEnum.NOT_STARTED.getCode())) {
            throw new BizException(ResultCodeEnum.ACTIVITY_NOT_START.getCode(), 
                                  ResultCodeEnum.ACTIVITY_NOT_START.getMessage());
        }
        if (activity.getActivityStatus().equals(ActivityStatusEnum.ENDED.getCode())) {
            throw new BizException(ResultCodeEnum.ACTIVITY_ENDED.getCode(),
                                 ResultCodeEnum.ACTIVITY_ENDED.getMessage());
        }
        if (now.isBefore(activity.getStartTime()) || now.isAfter(activity.getEndTime())) {
            throw new BizException(ResultCodeEnum.ACTIVITY_TIME_INVALID.getCode(),
                                 ResultCodeEnum.ACTIVITY_TIME_INVALID.getMessage());
        }
        
        return activity;
    }

    /**
     * 校验参与次数
     */
    private void checkParticipationLimit(Integer userId, Integer activityId) {
        int todayCount = participationMapper.countTodayParticipation(userId, activityId);
        if (todayCount >= 3) {
            throw new BizException(ResultCodeEnum.PARTICIPATION_LIMIT.getCode(), 
                                  ResultCodeEnum.PARTICIPATION_LIMIT.getMessage());
        }
    }

    /**
     * 记录参与
     */
    private void recordParticipation(Integer userId, Integer activityId, String ipAddress, String deviceId) {
        LotteryParticipation participation = new LotteryParticipation();
        participation.setUserId(userId);
        participation.setActivityId(activityId);
        participation.setParticipateTime(LocalDateTime.now());
        participation.setIpAddress(ipAddress);
        participation.setDeviceId(deviceId);
        participationMapper.insert(participation);
    }

    /**
     * 抽奖
     */
    private LotteryPrize drawPrize(Integer activityId) {
        List<LotteryPrize> prizes = prizeMapper.selectList(
            new LambdaQueryWrapper<LotteryPrize>()
                .eq(LotteryPrize::getActivityId, activityId)
                .gt(LotteryPrize::getRemainingQuantity, 0)
        );
        
        if (prizes.isEmpty()) {
            return null;
        }

        // 计算总概率
        double totalProbability = prizes.stream()
            .mapToDouble(prize -> prize.getProbability().doubleValue())
            .sum();

        // 随机抽取
        double randomValue = random.nextDouble() * totalProbability;
        double currentSum = 0;
        
        for (LotteryPrize prize : prizes) {
            currentSum += prize.getProbability().doubleValue();
            if (randomValue <= currentSum) {
                return prize;
            }
        }
        
        return null;
    }

    /**
     * 记录中奖
     */
    private LotteryWinner recordPrizeWinner(Integer userId, Integer activityId, Integer prizeId) {
        LotteryWinner winner = new LotteryWinner();
        winner.setUserId(userId);
        winner.setActivityId(activityId);
        winner.setPrizeId(prizeId);
        winner.setWinTime(LocalDateTime.now());
        winner.setPrizeStatus(0); // 未领取
        winnerMapper.insert(winner);
        return winner;
    }

    /**
     * 领取奖品
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean claimPrize(Long winnerId) {
        return winnerMapper.updatePrizeStatus(winnerId, 1) > 0;
    }
} 